# -*- coding: utf-8 -*-
from tkinter import Tk
from tkinter import Scrollbar
from tkinter import Frame
from tkinter import Label
from tkinter import Entry
from tkinter import filedialog
from tkinter import StringVar
from tkinter import BooleanVar
from tkinter import Button
from tkinter import Radiobutton
from tkinter import Text
from tkinter import HORIZONTAL
from tkinter import LEFT
from tkinter import RIGHT
from tkinter import BOTTOM
from tkinter import BOTH
from tkinter import Y
from tkinter import X
from tkinter import YES
from tkinter import END
from tkinter import DISABLED
from tkinter import ACTIVE
from tkinter import NORMAL
from tkinter import messagebox
from threading import Event
from threading import Thread
from SuperEmailSender.base_class import BaseClass
from SuperEmailSender.send_email import SendEmail
from SuperEmailSender.settings import BASE_DIR
from SuperEmailSender.settings import CONFIG_FILE_PATH
from SuperEmailSender.settings import LOG_LEVEL
from SuperEmailSender.settings import VERSION
from SuperEmailSender.settings import config


class Main(BaseClass):
    name = 'main'

    def __init__(self, *args, **kwargs):
        super(Main, self).__init__(*args, **kwargs)
        self.set_setting()
        self.index_frame()

    def _update_online(self, interval):
        entry_list = [self.entry_host, self.entry_account, self.entry_passwd, self.entry_path, self.entry_port,
                      self.entry_timeout, self.entry_retry]
        button_list = [self.entry_passwd_button, self.entry_button, self.start_button] + self.format_button + self.connection_button + self.validate_certs_button
        while not self.event.wait(interval):
            try:
                if self.event.isSet(): break
                BaseClass.log_level = self.log_level_var.get()
                if self.server_threading and self.server_threading.is_alive():
                    self.frame_from_right.configure(highlightbackground="red", highlightcolor="red", highlightthickness=1)
                    for entry in entry_list: entry['state'] = DISABLED
                    for button in button_list: button['state'] = DISABLED
                else:
                    self.frame_from_right.configure(highlightbackground="blue", highlightcolor="blue", highlightthickness=1)
                    for entry in entry_list: entry['state'] = NORMAL
                    for button in button_list: button['state'] = ACTIVE
            except Exception as e:
                self.logger.error(repr(e))

    def _start_server(self):
        self.frame_from_right.configure(highlightbackground="red", highlightcolor="red", highlightthickness=1)
        entry_list = [self.entry_host, self.entry_account, self.entry_passwd, self.entry_path, self.entry_port,
                      self.entry_timeout, self.entry_retry]
        button_list = [self.entry_passwd_button, self.entry_button, self.start_button] + self.format_button + self.connection_button + self.validate_certs_button
        for entry in entry_list: entry['state'] = DISABLED
        for button in button_list: button['state'] = DISABLED
        host = self.entry_host.get().strip()
        port = self.entry_port.get().strip()
        timeout = self.entry_timeout.get().strip()
        retry = self.entry_retry.get().strip()
        account = self.entry_account.get().strip()
        passwd = self.entry_passwd.get().strip()
        path = self.entry_path.get().strip()
        format_var = self.format_var.get()
        connection = self.connection_var.get()
        validate_certs = self.validate_certs_var.get()

        if not host: messagebox.showwarning('警告', 'SMTP服务地址不能为空')
        if not port: messagebox.showwarning('警告', '端口号不能为空')
        if not account: messagebox.showwarning('警告', '发件人不能为空')
        if not path: messagebox.showwarning('警告', '未选择文件')
        if all([host, port, account, path]) and (not self.server_threading or not self.server_threading.is_alive()):
            self.text_log.delete(0.0, END)
            self.root.update()
            kwargs = {'target': self.send_email.create_employee_data,
                      'args': (host, port, account, passwd, format_var, path),
                      'kwargs': {'use_tls': connection, 'timeout': int(timeout),
                                 'validate_certs': validate_certs, 'retry': int(retry)},
                      'name': 'send_email', 'daemon': True}
            self.server_threading = Thread(**kwargs)
            self.server_threading.start()

    def print_password(self):
        if self.entry_passwd['show']: self.entry_passwd['show'] = ''
        else: self.entry_passwd['show'] = '*'

    def open_file(self):
        filetypes = (
            ('Excel 2003', '*.xls'),
            ('Excel 2007', '*.xlsx'),
            ('All files', '*.*')
        )

        filename = filedialog.askopenfilename(
            title='选择一个文件',
            initialdir=BASE_DIR,
            filetypes=filetypes)
        self.entry_path.delete(0, END)
        self.entry_path.insert(END, filename)

    def close(self):
        self.event.set()
        threading_list = [self.server_threading, self.online_threading]
        for threading_ in threading_list:
            while threading_ and threading_.is_alive():
                pass
        host = self.entry_host.get().strip()
        port = self.entry_port.get().strip()
        timeout = self.entry_timeout.get().strip()
        account = self.entry_account.get().strip()
        passwd = self.entry_passwd.get().strip()
        retry = self.entry_retry.get().strip()
        format_var = self.format_var.get()
        connection = self.connection_var.get()
        validate_certs = self.validate_certs_var.get()
        config.config.set('LOGGING', 'level', self.log_level_var.get())
        config.config.set('EMAIL', 'connection', str(connection))
        config.config.set('EMAIL', 'validate_certs', str(validate_certs))
        config.config.set('FORMAT', 'format_design', str(format_var))
        if host: config.config.set('EMAIL', 'host', host)
        if port: config.config.set('EMAIL', 'port', port)
        if timeout: config.config.set('EMAIL', 'timeout', timeout)
        if account: config.config.set('EMAIL', 'account', account)
        if passwd: config.config.set('EMAIL', 'passwd', passwd)
        if retry: config.config.set('EMAIL', 'retry', retry)
        config.save_file(CONFIG_FILE_PATH, config.config)
        self.root.quit()
        self.root.destroy()

    def set_setting(self):
        self.width = 1280
        self.height = 720
        self.server_threading = None
        self.online_threading = None
        self.send_email = SendEmail()
        self.event = Event()
        self.root = Tk()
        self.root.title('SMTP批量发送工资条邮件')
        self.root.geometry(f"{self.width}x{self.height}")
        self.root.resizable(width=False, height=False)
        self.root.protocol("WM_DELETE_WINDOW", lambda : self.close())
        self.frame = Frame(self.root)
        self.frame.grid(row=0, column=0, sticky='nsew')

    def index_frame(self):
        frame_from = Frame(self.frame)
        frame_log = Frame(self.frame)
        self.set_frame_from(frame_from)
        self.set_frame_log(frame_log)
        frame_log.grid(row=1, column=0, padx=0, pady=0, sticky='nsew')
        frame_from.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')
        self.online_threading = Thread(target=self._update_online, args=(1,), name='update_online', daemon=True)
        self.online_threading.start()

    def set_frame_from(self, frame):
        frame_from = Frame(frame)
        frame_from_left = Frame(frame_from)
        self.set_from_data(frame_from_left)
        self.set_logger_bottom(frame_from_left)
        self.set_open_file(frame_from_left)
        frame_from_left.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')

        self.frame_from_right = Frame(frame_from, highlightbackground="blue", highlightcolor="blue", highlightthickness=1)
        self.start_button = Button(self.frame_from_right, text="开始发送", width=20, height=5, command=self._start_server)
        self.start_button.pack(side=LEFT, fill=BOTH, expand=True)
        self.frame_from_right.grid(row=0, column=1, padx=0, pady=0, sticky='nsew')

        frame_from.grid(row=0, column=0, padx=10, pady=10, sticky='nsew')

    def set_frame_log(self, frame):
        frame_ = Frame(frame)
        frame_log = Frame(frame_)
        s_y = Scrollbar(frame_log)
        s_x = Scrollbar(frame_log, orient=HORIZONTAL)
        s_y.pack(side=RIGHT, fill=Y)
        s_x.pack(side=BOTTOM, fill=X)
        self.text_log = Text(frame_log, width=178, height=40, yscrollcommand=s_y.set, xscrollcommand=s_x.set, wrap='none')
        self.text_log.bind("<Key>", lambda e: "break")
        self.text_log.pack(expand=YES, fill=BOTH)
        BaseClass.text_log = self.text_log
        s_y.config(command=self.text_log.yview)
        s_x.config(command=self.text_log.xview)
        version = Label(frame_, text=f'当前版本: {VERSION}')
        frame_log.grid(row=0, column=0, padx=0, pady=0, sticky='nsw')
        version.grid(row=1, column=0, padx=0, pady=0, sticky='nsw')
        frame_.grid(row=0, column=0, padx=10, pady=0, sticky='nsew')

    def set_from_data(self, frame):
        frame_from = Frame(frame)

        frame_host = Frame(frame_from)
        label_host = Label(frame_host, text='邮箱SMTP服务地址')
        label_port = Label(frame_host, text='端口号')
        label_timeout = Label(frame_host, text='超时时间')
        label_retry = Label(frame_host, text='重试次数')
        self.entry_host = Entry(frame_host, width=45, textvariable=StringVar(value=config.config['EMAIL']['host']))
        self.entry_port = Entry(frame_host, width=8, textvariable=StringVar(value=config.config['EMAIL']['port']))
        self.entry_timeout = Entry(frame_host, width=8, textvariable=StringVar(value=config.config['EMAIL']['timeout']))
        self.entry_retry = Entry(frame_host, width=6, textvariable=StringVar(value=config.config['EMAIL']['retry']))
        label_host.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')
        self.entry_host.grid(row=0, column=1, padx=10, pady=0, sticky='e')

        label_port.grid(row=0, column=2, padx=13, pady=0, sticky='nsew')
        self.entry_port.grid(row=0, column=3, padx=5, pady=0, sticky='e')
        label_timeout.grid(row=0, column=4, padx=2, pady=0, sticky='nsew')
        self.entry_timeout.grid(row=0, column=5, padx=5, pady=0, sticky='e')
        label_retry.grid(row=0, column=6, padx=2, pady=0, sticky='nsew')
        self.entry_retry.grid(row=0, column=7, padx=5, pady=0, sticky='e')
        frame_host.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')

        frame_account = Frame(frame_from)
        label_account = Label(frame_account, text='发件人')
        self.entry_account = Entry(frame_account, width=100, textvariable=StringVar(value=config.config['EMAIL']['account']))
        label_account.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')
        self.entry_account.grid(row=0, column=1, padx=80, pady=0, sticky='e')
        frame_account.grid(row=1, column=0, padx=0, pady=0, sticky='nsew')

        frame_passwd = Frame(frame_from)
        label_passwd = Label(frame_passwd, text='密码')
        entry_passwd_frame = Frame(frame_passwd)
        self.entry_passwd = Entry(entry_passwd_frame, width=100, show='*', textvariable=StringVar(value=config.config['EMAIL']['passwd']))
        self.entry_passwd_button = Button(entry_passwd_frame, text="显示密码", command=self.print_password)
        label_passwd.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')
        self.entry_passwd.grid(row=0, column=0, padx=0, pady=0, sticky='e')
        self.entry_passwd_button.grid(row=0, column=1, padx=0, pady=0, sticky='e')
        entry_passwd_frame.grid(row=0, column=1, padx=92, pady=0, sticky='nsew')
        frame_passwd.grid(row=2, column=0, padx=0, pady=0, sticky='nsew')

        frame_from.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')

    def set_logger_bottom(self, frame):
        log_level_var = ['DEBUG', 'INFO', 'WARNING', 'ERROR']
        self.log_level_var = StringVar()
        self.log_level_var.set(LOG_LEVEL)
        format_var, format_name = [True, False], ['竖版', '横板']
        self.format_var = BooleanVar()
        self.format_var.set(config.config['FORMAT']['format_design'])
        connection_var, connection_name = [True, False], ['TLS/SSL(加密连接)', 'TLS/SSL(明文连接)']
        self.connection_var = BooleanVar()
        self.connection_var.set(config.config['EMAIL']['connection'])
        validate_certs_var, validate_certs_name = [True, False], ['验证证书', '不验证证书']
        self.validate_certs_var = BooleanVar()
        self.validate_certs_var.set(config.config['EMAIL']['validate_certs'])
        frame_bottom = Frame(frame)

        radio_bottom_frame = Frame(frame_bottom)
        radio_button = [Radiobutton(radio_bottom_frame, text=level, variable=self.log_level_var, value=level) for level in log_level_var]
        for _, button in enumerate(radio_button): button.grid(row=0, column=_, padx=0, pady=0)
        radio_bottom_frame.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')

        format_bottom_frame = Frame(frame_bottom)
        self.format_button = [Radiobutton(format_bottom_frame, text=formats[1], variable=self.format_var, value=formats[0]) for formats in zip(format_var, format_name)]
        for _, button in enumerate(self.format_button): button.grid(row=0, column=_, padx=0, pady=0)
        format_bottom_frame.grid(row=0, column=1, padx=4, pady=0, sticky='nsew')

        connection_bottom_frame = Frame(frame_bottom)
        self.connection_button = [Radiobutton(connection_bottom_frame, text=connections[1], variable=self.connection_var, value=connections[0]) for connections in zip(connection_var, connection_name)]
        for _, button in enumerate(self.connection_button): button.grid(row=0, column=_, padx=0, pady=0)
        connection_bottom_frame.grid(row=0, column=2, padx=4, pady=0, sticky='nsew')

        validate_certs_bottom_frame = Frame(frame_bottom)
        self.validate_certs_button = [Radiobutton(validate_certs_bottom_frame, text=validate_certs[1], variable=self.validate_certs_var, value=validate_certs[0]) for validate_certs in zip(validate_certs_var, validate_certs_name)]
        for _, button in enumerate(self.validate_certs_button): button.grid(row=0, column=_, padx=0, pady=0)
        validate_certs_bottom_frame.grid(row=0, column=3, padx=4, pady=0, sticky='nsew')

        frame_bottom.grid(row=1, column=0, padx=0, pady=0, sticky='nsew')

    def set_open_file(self, frame):
        frame_file = Frame(frame)
        frame_path = Frame(frame_file)
        label_path = Label(frame_path, text='文件路径')
        entry_path_frame = Frame(frame_path)
        self.entry_path = Entry(entry_path_frame, width=100, textvariable=StringVar(value=''))
        self.entry_button = Button(entry_path_frame, text="选择文件", command=self.open_file)
        label_path.grid(row=0, column=0, padx=0, pady=0, sticky='nsew')
        self.entry_path.grid(row=0, column=0, padx=0, pady=0, sticky='e')
        self.entry_button.grid(row=0, column=1, padx=0, pady=0, sticky='e')
        entry_path_frame.grid(row=0, column=1, padx=70, pady=0, sticky='nsew')
        frame_path.grid(row=2, column=0, padx=0, pady=0, sticky='nsew')
        frame_file.grid(row=2, column=0, padx=0, pady=0, sticky='nsew')

